//
//  DependencyEventRouter.m
//  vrmuApp
//
//  Created by Benz.L on 21/08/2018.
//  Copyright © 2018 广东瑞亚传媒发展有限公司. All rights reserved.
//

#import "DependencyEventRouter.h"

@class JYDependencyOperation;

typedef void(^ExecuteBlock) (JYDependencyOperation *opt);

@interface JYDependencyOperation : NSOperation
@property (nonatomic, strong) NSRecursiveLock *lock;
@property(nonatomic) ExecuteBlock executeBlock;

- (void)markAsFinised;

@end

@implementation JYDependencyOperation
@synthesize executing = _executing;
@synthesize finished = _finished;
@synthesize cancelled = _cancelled;

- (void)dealloc {
	NSLog();
}
- (instancetype)init {
	self = [super init];
	if (self) {
		_lock = [NSRecursiveLock new];
	}
	return self;
}

- (void)start {
	@autoreleasepool {
		[_lock lock];
		if ([self isCancelled]) {
			self.finished = YES;
			self.executing = NO;
		}
		else {
			self.executing = YES;
			if (_executeBlock) {
				_executeBlock(self);
			}
		}
		[_lock unlock];
	}
}

- (void)cancel {
	[_lock lock];
	if (![self isCancelled]) {
		[super cancel];
		self.cancelled = YES;
		if ([self isExecuting]) {
			self.executing = NO;
			self.finished = YES;
		}
	}
	[_lock unlock];
}

- (void)setExecuting:(BOOL)executing {
	[_lock lock];
	if (_executing != executing) {
		[self willChangeValueForKey:@"isExecuting"];
		_executing = executing;
		[self didChangeValueForKey:@"isExecuting"];
	}
	[_lock unlock];
}

- (BOOL)isExecuting {
	[_lock lock];
	BOOL executing = _executing;
	[_lock unlock];
	return executing;
}

- (void)setFinished:(BOOL)finished {
	[_lock lock];
	if (_finished != finished) {
		[self willChangeValueForKey:@"isFinished"];
		_finished = finished;
		[self didChangeValueForKey:@"isFinished"];
	}
	[_lock unlock];
}

- (BOOL)isFinished {
	[_lock lock];
	BOOL finished = _finished;
	[_lock unlock];
	return finished;
}

- (void)setCancelled:(BOOL)cancelled {
	[_lock lock];
	if (_cancelled != cancelled) {
		[self willChangeValueForKey:@"isCancelled"];
		_cancelled = cancelled;
		[self didChangeValueForKey:@"isCancelled"];
	}
	[_lock unlock];
}

- (BOOL)isCancelled {
	[_lock lock];
	BOOL cancelled = _cancelled;
	[_lock unlock];
	return cancelled;
}

- (void)markAsFinised {
	self.finished = YES;
}

@end

const char kCycleKey = '\0';

@interface DependencyEvent()
@property(nonatomic, strong) JYDependencyOperation *opt;
@end
@implementation DependencyEvent

- (void)dealloc {
	[_opt removeObserver:self forKeyPath:@"isFinished"];
	[_opt removeObserver:self forKeyPath:@"isCancelled"];
}

- (instancetype)initWithExecuteBlock:(void(^)(DependencyEvent *event))block {
	self = [super init];
	if (self) {
		__weak DependencyEvent *weak = self;
		_opt = [[JYDependencyOperation alloc] init];
		_opt.executeBlock = ^(JYDependencyOperation *opt) {
			dispatch_async(dispatch_get_main_queue(), ^{
				if (block) {
					block(weak);
				}
			});
		};
		objc_setAssociatedObject(_opt, &kCycleKey, self, OBJC_ASSOCIATION_RETAIN);
		[_opt addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:NULL];
		[_opt addObserver:self forKeyPath:@"isCancelled" options:NSKeyValueObservingOptionNew context:NULL];
	}
	return self;
}

- (void)setEventFinished:(BOOL)eventFinished {
	_eventFinished = eventFinished;
	[_opt markAsFinised];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
	if (object==_opt) {
		objc_setAssociatedObject(_opt, &kCycleKey, nil, OBJC_ASSOCIATION_RETAIN);
	}
}

@end

@interface DependencyEventRouter() {
	NSOperationQueue *_queue;
}
@end
@implementation DependencyEventRouter

- (instancetype)init {
	self = [super init];
	if (self) {
		_queue = [[NSOperationQueue alloc] init];
		_queue.maxConcurrentOperationCount = 1;
	}
	return self;
}

- (void)addDependencyEvent:(DependencyEvent *)event {
	[_queue addOperation:event.opt];
}

- (void)cancellAllEvents {
	[_queue cancelAllOperations];
}

@end
